package pl.edu.agh.mobicentsVoIP.database;

import java.util.Collection;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Restrictions;

import pl.edu.agh.mobicentsVoIP.core.Call;
import pl.edu.agh.mobicentsVoIP.core.CallStatus;
import pl.edu.agh.mobicentsVoIP.core.User;


// Twoja klasa Błażej do implementacji połączenia jeśli będzie trzeba dodać 
//jeszcze jakieś klaski do obsługi połączeń to w tym pakiecie
public class HSQLFacade implements IFacade {

	private static final SessionFactory sessionFactory;
	static {
		try {
			sessionFactory = new Configuration().configure()
					.buildSessionFactory();
		} catch (Throwable ex) {
			System.err.println("Initial SessionFactory creation failed." + ex);
			throw new ExceptionInInitializerError(ex);
		}
	}

	public void addCall(Call call) {
		Session session = sessionFactory.openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			session.save(call);
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	public void endCall(Call call) {
		call.setStatus(CallStatus.OVER);
		Session session = sessionFactory.openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			session.update(call);
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	public void registerUser(User user) {
		Session session = sessionFactory.openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			user.setRegistered(true);
			session.saveOrUpdate(user);
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	public void unRegisterUser(User user) {
		Session session = sessionFactory.openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			session.createQuery(
					"update User u set registered = false where u.id = :id")
					.setString("id", user.getName() + "").executeUpdate();
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	public User getUserByUserURI(String userURI) {
		Session session = sessionFactory.openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			User user = (User) session.createCriteria(User.class)
					.add(Restrictions.eq("userURI", userURI)).uniqueResult();
			transaction.commit();
			return user;
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		return null;
	}

	public User getUser(String name) {
		Session session = sessionFactory.openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			User user = (User) session.createCriteria(User.class)
					.add(Restrictions.eq("name", name)).uniqueResult();
			transaction.commit();
			return user;
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		return null;
	}
	
	public Call getCallByUsersURIs(String fromURI, String toURI) {
		User u1 = getUserByUserURI(fromURI);
		User u2 = getUserByUserURI(toURI);
		Session session = sessionFactory.openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			Call call = (Call) session.createCriteria(Call.class)
					.add(Restrictions.eq("from", u1))
					.add(Restrictions.eq("to", u2)).uniqueResult();
			transaction.commit();
			return call;
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		return null;
	}

	public Collection<Call> getAllCalls() {
		Session session = sessionFactory.openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			List list = session.createCriteria(Call.class).list();
			transaction.commit();
			return list;
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		return null;
	}

	public Collection<User> getAllUsers() {
		Session session = sessionFactory.openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			List list = session.createCriteria(User.class).list();
			transaction.commit();
			return list;
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		return null;
	}

	public Collection<User> getRegisteredUsers(boolean registered) {
		Session session = sessionFactory.openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			List list = session.createCriteria(User.class)
					.add(Restrictions.eq("registered", registered)).list();
			transaction.commit();
			return list;
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		return null;
	}

	public Collection<Call> getAllUserCalls(User user) {
		Session session = sessionFactory.openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			List list = session
					.createCriteria(Call.class)
					.add(Restrictions.disjunction()
							.add(Restrictions.eq("from", user))
							.add(Restrictions.eq("to", user))).list();
			transaction.commit();
			return list;
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		return null;
	}

}
